fix(app-shell,components): 服务端声明动作的 visible 门按「已声明」判定,visible: false 不再渲染 (#3835) - #3843
Merged
Merged
Conversation
…不再渲染 (#3835) DeclaredActionsBar 的门沿用真值判读 `if ((action as any).visible && !isVisible) return null`,于是 `visible: false` 落进「没声明门」分支,verdict 从未被查询,动作照样渲染。 这是 #3492 同族第五处,也是两条族群缓解在此都不成立的一处: - 动作 def 是服务端声明的(objectDef.actions[]、sys_approval_request), 不是手写视图 JSON。「ActionSchema.visible 是 ExpressionInputSchema、无 boolean 成员,objectstack build 产不出布尔形状」这条缓解在这条路径上不 成立 —— def 来自服务端 metadata 与进程内构造,布尔是自然写法。 - 该 bar 由宿主以普通 JSX 直挂(apps/console 的 ApprovalsInboxPage), packages/react 的 SchemaRenderer 不在这条路径上,#3812 判定组件级门休眠 的依据(宿主先求值 visible 再隐藏)不适用。这个门是该路径上唯一的门。 宿主是审批收件箱的记录区动作条:一个本该被 visible: false 关掉的审批动作 渲染成可点按钮,而本组件自己的 click handler 就是 POST 审批决定的那一步。 门统一到同族那一处命名定义 hasDeclaredVisibilityGate(`!= null && !== ''`), 从 @object-ui/components 的 barrel 新增一行 re-export 引入,不抄第五份 (#3142 的 locations 漂移形)。verdict 仍交给求值入口:toPredicateInput 原样透传布尔、useCondition 在 evaluateCondition 短路,故声明的 false 即 false,表达式取值的 visible verdict 一律不变。 先收紧常真桩,再落钉子:原套件把整个求值入口打桩成 `useCondition: () => true`,注释还写着测试动作不带 visible「所以用不到」—— 这让唯一挂载本组件的 套件里这道门从未被行使(#4984 族:fixture 让坏规则保持绿色)。现在改为只 替换动作派发,useCondition / toPredicateInput 用真实实现,四形状由出货语义 判定。 钉子:false 隐藏 / true 渲染 / 未声明渲染 / `''` 不算门 + 表达式两向 verdict + 隐藏动作在工具栏里不留任何可点面(按钮集断言,而非派发计数 —— 未被点击的 多余按钮在两侧都不派发,计数版修前也是绿的)。每例都带一个无门同伴动作, 使「未渲染」不会被误读成「整条 bar 返回 null」。 行为变化面(窄):只有 visible 为字面布尔 false(或其他非空 falsy)的声明 动作从渲染变隐藏;visible: true、`''`、未声明一律不变。 Claude-Session: https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt Co-authored-by: Claude <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
「fixture 让坏规则保持绿色」那一族是 objectstack(framework)仓的 #4984 (见其 packages/lint 内多处裸引用),objectui 侧要按本仓约定写成 objectstack#4984,否则指向本仓一个不存在的号。 Claude-Session: https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt Co-authored-by: Claude <noreply@anthropic.com>
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
Collaborator
Author
|
✅ 验收通过(objectui 分片 PM,session_01GTRjn8xBqp75dk7kFupVRt)—— undraft + auto-merge。 核验:三件按裁定落地(barrel 一行 re-export、门收口、桩收紧),且桩收紧优于要求 —— importOriginal 偏 mock 只替换 ActionProvider/useAction、求值入口用真实实现,避免在测试替身里出现被测语义的第二份拷贝; Generated by Claude Code |
yinlianghui
marked this pull request as ready for review
August 8, 2026 19:38
This was referenced Aug 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #3835
门:前后对照
packages/app-shell/src/views/DeclaredActionsBar.tsxfalse && …为假 → 不return null→ 渲染。作者写visible: false(最明确的「永不显示」)被真值判读成「没声明门」,verdict 从未被查询。hasDeclaredVisibilityGate(!= null && !== '')从@object-ui/components的 barrel 新增一行 re-export 引入(PM 已裁),不上提 core、不抄第五份(#3142 的locations漂移形):packages/components/src/index.tsverdict 仍交给求值入口,一行未动:
toPredicateInput原样透传布尔、useCondition在evaluateCondition短路,故声明的false即false,表达式取值的 verdict 一律不变。为什么这处是同族最热的一处
objectDef.actions[]/sys_approval_request)。「ActionSchema.visible是ExpressionInputSchema、无 boolean 成员,objectstack build产不出布尔形状」这条族群缓解在这条路径上不成立 —— def 来自服务端 metadata 与进程内构造,布尔是自然写法。apps/console/src/pages/system/ApprovalsInboxPage.tsx:2014/:2055),packages/react的SchemaRenderer不在路径上 —— components/action/**: 同一真值可见性门在动作面上未收口 ——action:group/action:menu成员动作声明visible: false照样渲染(#3758 的同族部分) #3812 判定组件级门休眠的依据(宿主先按visible !== undefined求值并隐藏)在此不适用。这个门是该路径上唯一的门。visible: false关掉的审批动作渲染成可点的 Approve/Reject,而本组件自己的 click handler 就是 POST 审批决定的那一步。桩收紧(先做,否则钉子空绿 —— #4984 族)
原套件把整个求值入口打桩成常真,注释还写着测试动作不带
visible「所以用不到」:这让唯一挂载本组件的套件里这道门从未被行使过。重新拼一个「布尔短路」的桩并不能修好这点:
visible: false走到「隐藏」依赖toPredicateInput透传布尔 +evaluateCondition短路,桩就是这套语义的第二份拷贝。改法是只替换动作派发,求值入口用真实实现:@object-ui/react的 barrel 对 lightdom项目是可负担的(components 自己的门套件就是不打桩地 import 它)。components 的 barrel 仍打桩(它的重图正是 light 项目故意不加载的),但hasDeclaredVisibilityGate从真实源模块取(纯函数、零依赖)—— 在测试替身里重拼一份!= null && !== ''会变成这条定义的第五份拷贝,并且无论出货谓词怎么变都保持绿色。钉子(四形状 + 同伴动作)
packages/app-shell/src/views/__tests__/DeclaredActionsBar.test.tsx新增 6 例,每例都带一个无门同伴动作(approval_reassign),使「未渲染」不会被误读成「整条 bar 返回 null」(空 located 集是两行之外的另一条码路)。反向验证(方向先判后跑)
判定: 修前
visible: false的钉子应红,true/ 未声明 /''/ 表达式两向应绿。实跑一致 —— 修前(桩已收紧、源未改):修后:
Tests 20 passed (20)。抗空绿变异(#3836 范式),两个方向,一个如预期一个不如:
if (true) return null)→ 15 红(含visible:true/ 未声明 /''/ 表达式为真四例,以及原有 9 例)。如预期:一个「把成员一律隐藏」的改写无法让这套钉子保持绿色。visible !== undefined,让''算门)→ 20 全绿。与我事先的判定相反,如实记录:这条路径上''被保护了两层 —— 门放过去之后,toPredicateInput('')是undefined,evaluateCondition(undefined)读作「没有条件 → 可见」。所以''那一例记录的是意图语义,在本面不是变异探测器;!== ''这条腿本身钉在packages/components定义旁边。这一点已写进测试的 docblock,以免下个读者把它的通过当成该腿被行使的证明。验证
仓根 flock +
NODE_OPTIONS=--max-old-space-size=4096+--maxWorkers=2:vitest run packages/app-shell/src/views/__tests__/DeclaredActionsBar.test.tsxTests 20 passed (20)vitest run packages/app-shell/src/views/__tests__/Test Files 10 passed / Tests 62 passedvitest run packages/components/src/renderers/action packages/components/src/__tests__/snapshot-critical.test.tsxTest Files 4 passed / Tests 57 passedpnpm --filter @object-ui/components type-checktsc --noEmit+ typetests)pnpm --filter @object-ui/app-shell type-checkpnpm --workspace-concurrency=2 --filter '@object-ui/app-shell^...' build起依赖 dist;packages/components/dist/index.d.ts已含新导出)eslint(三个改动文件)no-explicit-anywarning)node scripts/check-control-bytes.mjs[\x00-\x08\x0b\x0c\x0e-\x1f]零命中)消费半径清扫:全仓仅此一处套件挂载
DeclaredActionsBar(apps/console无 ApprovalsInboxPage 测试);barrel 改动是纯新增,无导出名冲突,components 侧无公共导出面快照断言。未动 / 不在本 PR 范围
action-group.tsx:235/action-bar.tsx:223/action-menu.tsx:179的三处组件级真值门照旧 —— 它们只经SchemaRenderer挂载(components/action/**:action:bar成员动作的组件级真值可见性门实证可达 ——action:button/action:icon声明visible: false照样渲染(#3812 第 3 条复核结论) #3823 / PR fix(components): action:bar 成员动作声明 visible: false 时隐藏而非渲染 (#3823) #3836 已如此裁定并写进 changeset)。disabled的「已声明」判定用!= null,disabled: ''把按钮永久置灰(#3492 同族的另一半 predicate,探针实证) #3842,未认领,未在本 PR 修):disabled的「已声明」判定停在!= null(本文件按钮 props 处 +action-button.tsx:164),于是disabled: ''被判成已声明门、verdict 取「没有条件 → true」= 禁用,审批按钮永久置灰(与visible侧相反的失败方向)。探针已实证,证据在 动作disabled的「已声明」判定用!= null,disabled: ''把按钮永久置灰(#3492 同族的另一半 predicate,探针实证) #3842。Changeset
.changeset/declared-actions-bar-visible-gate-3835.md—@object-ui/app-shellpatch,写明审批面变化:visible: false的服务端声明动作从可点变隐藏。.changeset/components-export-declared-visibility-gate-3835.md—@object-ui/componentspatch,新增 barrel 导出(纯新增,本包无行为变化)。在飞交叠
与 #3808 同触
packages/components,但它改renderers/basic/text-input.tsx与plugin-detail,未触src/index.ts;本 PR 只在 barrel 加一行导出,取并集即可,无文本冲突。#3546 切片四(i18n)不相交。Generated by Claude Code